package design.pattern.application.CommandAndChain;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

/**
 * @program JavaBase
 * @description:
 * @author: zhanglu
 * @create: 2020-05-22 14:37:00
 */
public class ClassUtils {

    //根据父类查找到所有的子类，默认情况是子类和父类都在同一个包名下
    public static List<Class> getSonClass(Class fatherClass){
        List<Class> resClass = new ArrayList<>();
        String packageName = fatherClass.getPackage().getName();
        List<Class> packageClasses = getClasses(packageName);
        for (Class packageClass : packageClasses) {
            if(fatherClass.isAssignableFrom(packageClass) && !fatherClass.equals(packageClass)){
                resClass.add(packageClass);
            }
        }
        return resClass;
    }
    //从一个包中查找出所有的类，在jar包中不能查找
    private static List<Class> getClasses(String packageName){
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        String path = packageName.replace('.', '/');
        Enumeration<URL> resources = null;
        try {
            resources = classLoader.getResources(path);
        } catch (Exception e) {
            e.printStackTrace();
        }
        List<File> dirs = new ArrayList<>();
        while (resources.hasMoreElements()){
            URL resource = null;
            try {
                resource = resources.nextElement();
                String file = resource.getFile();
                file = URLDecoder.decode(file, "UTF-8");
                dirs.add(new File(file));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
        List<Class> classes = new ArrayList<>();
        for (File dir : dirs) {
            classes.addAll(findClasses(dir, packageName));
        }
        return classes;
    }
    private static List<Class> findClasses(File directory, String packageName){
        List<Class> classes = new ArrayList<>();
        if(!directory.exists()){
            return classes;
        }
        File[] files = directory.listFiles();
        for (File file : files) {
            if(file.isDirectory()){
                classes.addAll(findClasses(file, packageName + "." + file.getName().substring(0, file.getName().indexOf('.'))));
            }else if(file.getName().endsWith(".class")){
                try {
                    classes.add(Class.forName(packageName + "." + file.getName().substring(0, file.getName().indexOf('.'))));
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            }
        }
        return classes;
    }

}
